<!DOCTYPE html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    
    <title>HTTP Method for REST API | Wonderland</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1">
    <meta name="description" content="HTTP 1.1 协议 RFC 族谱中和Method 定义相关的主要 RFC：
January 1997  RFC 2068 Hypertext Transfer Protocol — HTTP/1.1 (Obsoleted)
 June 1999  RFC 2616 Hypertext Transfer Protocol — HTTP/1.1 (Obsoleted)
 March 2010  RFC 5789 PATCH Method for HTTP (Obsoleted)
 June 2014  RFC 7230 Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
  RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
 HTTP Method 是体现 REST API 语义最重要的组成部分之一。例如最常见的CREATE/READ/UPDATE/DELETE （即CRUD 操作）映射到HTTP Method POST/GET/PUT/DELETE（虽然常见但并不严谨，详见下文）。">
    <meta name="generator" content="Hugo 0.76.5" />
    
    
      <META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
    

    
    
      <link href="/dist/css/app.4fc0b62e4b82c997bb0041217cd6b979.css" rel="stylesheet">
    

    

    
      

    

    
    
    <meta property="og:title" content="HTTP Method for REST API" />
<meta property="og:description" content="HTTP 1.1 协议 RFC 族谱中和Method 定义相关的主要 RFC：
January 1997  RFC 2068 Hypertext Transfer Protocol — HTTP/1.1 (Obsoleted)
 June 1999  RFC 2616 Hypertext Transfer Protocol — HTTP/1.1 (Obsoleted)
 March 2010  RFC 5789 PATCH Method for HTTP (Obsoleted)
 June 2014  RFC 7230 Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
  RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
 HTTP Method 是体现 REST API 语义最重要的组成部分之一。例如最常见的CREATE/READ/UPDATE/DELETE （即CRUD 操作）映射到HTTP Method POST/GET/PUT/DELETE（虽然常见但并不严谨，详见下文）。" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://bbsmrdj.gitee.io/architecture/http-method-for-rest-api/" />
<meta property="article:published_time" content="2020-10-19T23:32:19+08:00" />
<meta property="article:modified_time" content="2020-10-19T23:32:19+08:00" />
<meta itemprop="name" content="HTTP Method for REST API">
<meta itemprop="description" content="HTTP 1.1 协议 RFC 族谱中和Method 定义相关的主要 RFC：
January 1997  RFC 2068 Hypertext Transfer Protocol — HTTP/1.1 (Obsoleted)
 June 1999  RFC 2616 Hypertext Transfer Protocol — HTTP/1.1 (Obsoleted)
 March 2010  RFC 5789 PATCH Method for HTTP (Obsoleted)
 June 2014  RFC 7230 Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
  RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
 HTTP Method 是体现 REST API 语义最重要的组成部分之一。例如最常见的CREATE/READ/UPDATE/DELETE （即CRUD 操作）映射到HTTP Method POST/GET/PUT/DELETE（虽然常见但并不严谨，详见下文）。">
<meta itemprop="datePublished" content="2020-10-19T23:32:19+08:00" />
<meta itemprop="dateModified" content="2020-10-19T23:32:19+08:00" />
<meta itemprop="wordCount" content="240">



<meta itemprop="keywords" content="" />
<meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="HTTP Method for REST API"/>
<meta name="twitter:description" content="HTTP 1.1 协议 RFC 族谱中和Method 定义相关的主要 RFC：
January 1997  RFC 2068 Hypertext Transfer Protocol — HTTP/1.1 (Obsoleted)
 June 1999  RFC 2616 Hypertext Transfer Protocol — HTTP/1.1 (Obsoleted)
 March 2010  RFC 5789 PATCH Method for HTTP (Obsoleted)
 June 2014  RFC 7230 Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
  RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
 HTTP Method 是体现 REST API 语义最重要的组成部分之一。例如最常见的CREATE/READ/UPDATE/DELETE （即CRUD 操作）映射到HTTP Method POST/GET/PUT/DELETE（虽然常见但并不严谨，详见下文）。"/>

	
  </head>

  <body class="ma0 avenir bg-near-white">

    
   
  

  <header>
    <div class="bg-black">
      <nav class="pv3 ph3 ph4-ns" role="navigation">
  <div class="flex-l justify-between items-center center">
    <a href="/" class="f3 fw2 hover-white no-underline white-90 dib">
      
        Wonderland
      
    </a>
    <div class="flex-l items-center">
      

      
      















    </div>
  </div>
</nav>

    </div>
  </header>



    <main class="pb7" role="main">
      
  
  <article class="flex-l flex-wrap justify-between mw8 center ph3">
    <header class="mt4 w-100">
      <aside class="instapaper_ignoref b helvetica tracked">
          
        ARCHITECTURES
      </aside>
      




  <div id="sharing" class="mt3">

    
    <a href="https://www.facebook.com/sharer.php?u=https://bbsmrdj.gitee.io/architecture/http-method-for-rest-api/" class="facebook no-underline" aria-label="share on Facebook">
      <svg height="32px"  style="enable-background:new 0 0 67 67;" version="1.1" viewBox="0 0 67 67" width="32px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M28.765,50.32h6.744V33.998h4.499l0.596-5.624h-5.095  l0.007-2.816c0-1.466,0.14-2.253,2.244-2.253h2.812V17.68h-4.5c-5.405,0-7.307,2.729-7.307,7.317v3.377h-3.369v5.625h3.369V50.32z   M33,64C16.432,64,3,50.569,3,34S16.432,4,33,4s30,13.431,30,30S49.568,64,33,64z" style="fill-rule:evenodd;clip-rule:evenodd;"/></svg>

    </a>

    
    
    <a href="https://twitter.com/share?url=https://bbsmrdj.gitee.io/architecture/http-method-for-rest-api/&amp;text=HTTP%20Method%20for%20REST%20API" class="twitter no-underline" aria-label="share on Twitter">
      <svg height="32px"  style="enable-background:new 0 0 67 67;" version="1.1" viewBox="0 0 67 67" width="32px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M37.167,22.283c-2.619,0.953-4.274,3.411-4.086,6.101  l0.063,1.038l-1.048-0.127c-3.813-0.487-7.145-2.139-9.974-4.915l-1.383-1.377l-0.356,1.017c-0.754,2.267-0.272,4.661,1.299,6.271  c0.838,0.89,0.649,1.017-0.796,0.487c-0.503-0.169-0.943-0.296-0.985-0.233c-0.146,0.149,0.356,2.076,0.754,2.839  c0.545,1.06,1.655,2.097,2.871,2.712l1.027,0.487l-1.215,0.021c-1.173,0-1.215,0.021-1.089,0.467  c0.419,1.377,2.074,2.839,3.918,3.475l1.299,0.444l-1.131,0.678c-1.676,0.976-3.646,1.526-5.616,1.568  C19.775,43.256,19,43.341,19,43.405c0,0.211,2.557,1.397,4.044,1.864c4.463,1.377,9.765,0.783,13.746-1.568  c2.829-1.673,5.657-5,6.978-8.221c0.713-1.716,1.425-4.851,1.425-6.354c0-0.975,0.063-1.102,1.236-2.267  c0.692-0.678,1.341-1.419,1.467-1.631c0.21-0.403,0.188-0.403-0.88-0.043c-1.781,0.636-2.033,0.551-1.152-0.402  c0.649-0.678,1.425-1.907,1.425-2.267c0-0.063-0.314,0.042-0.671,0.233c-0.377,0.212-1.215,0.53-1.844,0.72l-1.131,0.361l-1.027-0.7  c-0.566-0.381-1.361-0.805-1.781-0.932C39.766,21.902,38.131,21.944,37.167,22.283z M33,64C16.432,64,3,50.569,3,34S16.432,4,33,4  s30,13.431,30,30S49.568,64,33,64z" style="fill-rule:evenodd;clip-rule:evenodd;fill:;"/></svg>

    </a>

    
    <a href="https://www.linkedin.com/shareArticle?mini=true&amp;url=https://bbsmrdj.gitee.io/architecture/http-method-for-rest-api/&amp;title=HTTP%20Method%20for%20REST%20API" class="linkedin no-underline" aria-label="share on LinkedIn">
      <svg  height="32px"  style="enable-background:new 0 0 65 65;" version="1.1" viewBox="0 0 65 65" width="32px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <path d="M50.837,48.137V36.425c0-6.275-3.35-9.195-7.816-9.195  c-3.604,0-5.219,1.983-6.119,3.374V27.71h-6.79c0.09,1.917,0,20.427,0,20.427h6.79V36.729c0-0.609,0.044-1.219,0.224-1.655  c0.49-1.22,1.607-2.483,3.482-2.483c2.458,0,3.44,1.873,3.44,4.618v10.929H50.837z M22.959,24.922c2.367,0,3.842-1.57,3.842-3.531  c-0.044-2.003-1.475-3.528-3.797-3.528s-3.841,1.524-3.841,3.528c0,1.961,1.474,3.531,3.753,3.531H22.959z M34,64  C17.432,64,4,50.568,4,34C4,17.431,17.432,4,34,4s30,13.431,30,30C64,50.568,50.568,64,34,64z M26.354,48.137V27.71h-6.789v20.427  H26.354z" style="fill-rule:evenodd;clip-rule:evenodd;fill:;"/>
</svg>

    </a>
  </div>


      <h1 class="f1 athelas mt3 mb1">HTTP Method for REST API</h1>
      
      
      <time class="f6 mv4 dib tracked" datetime="2020-10-19T23:32:19+08:00">October 19, 2020</time>

      
      
    </header>
    <div class="nested-copy-line-height lh-copy serif f4 nested-links nested-img mid-gray pr4-l w-two-thirds-l"><p>HTTP 1.1 协议 RFC 族谱中和Method 定义相关的主要 RFC：</p>
<h5 id="january-1997">January 1997</h5>
<blockquote>
<p><a href="https://tools.ietf.org/html/rfc2068">RFC 2068 Hypertext Transfer Protocol — HTTP/1.1</a> (Obsoleted)</p>
</blockquote>
<h5 id="june-1999">June 1999</h5>
<blockquote>
<p><a href="https://tools.ietf.org/html/rfc2616">RFC 2616 Hypertext Transfer Protocol — HTTP/1.1</a> (Obsoleted)</p>
</blockquote>
<h5 id="march-2010">March 2010</h5>
<blockquote>
<p><a href="https://tools.ietf.org/html/rfc5789">RFC 5789 PATCH Method for HTTP</a> (Obsoleted)</p>
</blockquote>
<h5 id="june-2014">June 2014</h5>
<blockquote>
<p><a href="https://tools.ietf.org/html/rfc7230">RFC 7230 Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing</a></p>
</blockquote>
<blockquote>
<p><a href="https://tools.ietf.org/html/rfc7231">RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content</a></p>
</blockquote>
<p>HTTP Method 是体现 REST API 语义最重要的组成部分之一。例如最常见的CREATE/READ/UPDATE/DELETE （即CRUD 操作）映射到HTTP Method POST/GET/PUT/DELETE（虽然常见但并不严谨，详见下文）。</p>
<p>RFC 7231 定义了最常见的 8 种HTTP Method，加上RFC 5789 定义的PATCH，共9 种常见Method。</p>
<h5 id="get">GET</h5>
<p>GET 方法通常用于获得URI 所指定的资源。GET 的标准语义通过一系列Headers 定义了诸如条件检查，返回局部结果，以及缓存等功能。这些Headers 常被用于返回静态资源，并且精确支持其语义。但是在处理动态资源的时候，还有一种方法也很受欢迎，那就是URL Parameters，即问号（？）后面的参数。两者相比各有各的优劣：</p>
<p>Headers：并非URL 的一部分，易于结构化，对于程序化处理比较友好，并且能够支持较大的Payload，也无需做URL Encode。但是通常需要程序化处理，且浏览器地址栏不可见。
URL Parameters：URL 的一部分，浏览器地址栏可见，可单字符串收藏。但是长度受限比Headers 严重，且通常需要URL Encode。
比如，同样是过滤器，放置在Headers 和URL Parameters 里都有各自的好处。具体选择哪一种方案取决于项目API 的整体风格，以及该资源的属性。</p>
<h5 id="post">POST</h5>
<p>POST 通常用来被创建资源，该资源可以是持久化的，或者发起一个处理请求。后者很好的覆盖了大多数非“创建” 类的动作。</p>
<p>例如，我需要一杯咖啡这个请求，在有些语境下我们可以直接创建一个咖啡的资源，例如我不关心咖啡的来源，可以从星巴克买；有些情况下则需要从另一个资源来进行转换，比如从咖啡豆冲泡成咖啡。为了体现这种非创建型动作（冲泡），我们可以发起一个冲泡请求，请求里包含所有需要的资源，例如咖啡豆，咖啡机，冲泡参数等等。</p>
<p>在这个例子里，我们最终得到了一杯咖啡资源，但是这个请求事实上可以是任何动作，可以不创建资源，可以修改资源，删除资源等等。这也导致POST 经常被滥用，任何动作都可以用POST 来解决。使用POST 本身没什么不妥，问题在于对请求的适当抽象和归类，可以使用不代表可以滥用。</p>
<p>另外一点，POST 请求通常是非幂等的。这意味着同样的请求POST 一次或者多次会导致不同的系统状态。因此，发起POST 请求时应仔细检查是否需要保证 “有且仅有一次”或者 “最多一次” 的执行序。</p>
<h5 id="put">PUT</h5>
<p>PUT 通常被用来修改资源，但是当资源不存在时也可以创建资源。和POST 不一样的是，POST 通常是创建一个某种类型的资源，而PUT 是创建、修改指定的某一个资源。这也是为什么POST 请求通常不带资源标志符（ID），而PUT 请求一般都通过标志符指定特定资源。</p>
<p>另外一点就是，PUT 通常认为是覆盖式的操作，是幂等的。这意味着API 设计者应该保证对同一个资源的PUT 操作无论执行多少次都产生同一个系统状态。</p>
<h5 id="patch">PATCH</h5>
<p>PATCH 的语义和PUT 类似，用于修改资源，但是只修改差集指定的部分。API 的定义者应该明确该PATCH 的格式以及如何应用于指定的资源。但是，和PUT 不一样的是，PATCH 不是幂等的，服务器决定了如何处理PATCH 请求中对资源的修改。从这点来说，PATCH 的行为更接近于POST 一个请求，两者都可以是对某个资源进行修改，而修改的内容则不一定像PUT 那样直接，也可能是间接的，过程化的。</p>
<p>在大多数情况下，PATCH 能做的事情，PUT都能做，实在不行还有POST，因此很多API 实现都不会再多此一举支持PATCH 操作。这样的实践遵守了API 的正交性原则，对于基础级别的API，也推荐这样实现。而在面向应用的API 中（例如BFF – Backend For Frontend ），则不受这样的规则限制。相反，那些API 会更多的向应用需求倾斜。相比PUT，PATCH 有时候能够提供更佳的语义以及更小的数据交换量。</p>
<h5 id="delete">DELETE</h5>
<p>DELETE 的语义是删除指定的资源。一个常见的争论是，当删除一个不存在的资源的时候，是应该返回错误，还是应该返回成功。同样的争论也发生很多其他地方。例如在Java – HashMap 里，反复删除同一个Key 是不会报错的。但是在操作系统中，如果尝试对同一个资源地址进行删除操作，操作系统通常会抱怨该资源已不存在。</p>
<p>在RFC 7231 中，DELETE 操作是幂等的，这意味着按照该语义，重复DELETE 同一个资源应产生同样的系统状态。但是这并不意味着API 返回也必须一样。API 的行为常常受到API 使用者的用户体验影响，如果用户需要精确的反馈，报错会很有用；但是如果用户只在乎最终状态，并且希望简化资源的回收和状态管理，那么成功的静默返回也是一个不错的注意。</p>
<h5 id="head">HEAD</h5>
<p>HEAD 用于仅返资源回头部信息，通常包含资源的大小等属性，客户端可以以此决定后续GET 操作的具体实现，例如进度追踪，或者仅获取资源的部分结果等。RFC 7231 中，要求HEAD、GET 同一个资源必须返回一致的头部信息。在实际实现中，则常考虑HEAD 的实现比GET 要轻量。因为HEAD 不需要传输具体的资源内容，应考虑仅读取资源元数据，避免读取整个资源等重量级操作。</p>
<h5 id="options">OPTIONS</h5>
<p>OPTIONS 用于测试服务器处理资源的可选项，常见的例如针对某资源允许的Method，或者允许的跨域请求等。这里不多展开。</p>
<h5 id="traceconnect">TRACE，CONNECT</h5>
<p>在REST API 的环境系，TRACE，CONNECT 语义不常用，略过。</p>
<p>最后值得一提的是，从最早的RFC 2068 到最新的RFC 7230、7231，HTTP Method 都可以被定义为任意 “token”[1][2]。因此，在REST API 定义中，我们是可以自定义Method 的。这样做的理由常常是，他们比常见的这9 种Method 具有更加丰富，以及可能更加精确的语义。一个常见的梗是RFC 2324：Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0)，1998年的一个愚人节项目，也可以说是程序员的幽默 – 私以为用来展示HTTP 的可扩展性其实是挺好的例子。</p>
<p>但是，不这么做的理由看上去也很充分：</p>
<ul>
<li>和项目上下文有关的扩展HTTP Method 并非广为人知，意味着各类框架的支持会非常有限，结果就是常常很难，甚至无法做到。比如时至这篇文章的发表日期，Spring 框架的HttpMethod 就只有除了CONNECT 之外的8 个，不支持扩展Method。</li>
<li>可扩展意味着灵活，但是控制不好也会变成桎梏，导致API 语义混乱，不易于理解。所以需要组织级别的强有力的统一管理，确保扩展Method 的规范化，正交化，去重等，而不是随心所欲的定义。</li>
</ul>
<p>因此在大多数项目中，我看到的结果常常是为了管理、集成的方便而向传统的Method 妥协。更何况传统的Method 已经深入人心，几乎可以涵盖90% 以上的资源操作语义，我们也就不用费尽心思再去发明些什么。也许有一天物联网真的发达了，会出现支持类似RFC 2324 那种协议的茶壶吧；）。</p>
<p>References:</p>
<p>[1] “token” 定义参见：<a href="https://tools.ietf.org/html/rfc7230#section-3.2.6">RFC 7230/Section 3.2.6 Field Value Components</a></p>
<p>[2] 参见已注册的HTTP Method：IANA <a href="https://www.iana.org/assignments/http-methods/http-methods.xhtml">Hypertext Transfer Protocol (HTTP) Method Registry</a></p>
<ul class="pa0">
  
</ul>
<div class="mt6 instapaper_ignoref">
      
      
      </div>
    </div>

    <aside class="w-30-l mt6-l">




</aside>

  </article>

    </main>
    <footer class="bg-black bottom-0 w-100 pa3" role="contentinfo">
  <div class="flex justify-between">
  <a class="f4 fw4 hover-white no-underline white-70 dn dib-ns pv2 ph3" href="https://bbsmrdj.gitee.io" >
    &copy;  Wonderland 2020 
  </a>
    <div>














</div>
  </div>
</footer>

    

  <script src="/dist/js/app.3fc0f988d21662902933.js"></script>


  </body>
</html>
